package com.gae.onlinestore.services;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gae.onlinestore.entity.Customer;
import com.gae.onlinestore.entity.EntityManagerFactory;
import com.gae.onlinestore.entity.Product;
import com.gae.onlinestore.entity.ProductInBusket;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.gson.Gson;

public class ProductServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		if (req.getParameter("action").equalsIgnoreCase("insert")){
			processInsert(req,resp);
		}
		else if (req.getParameter("action").equalsIgnoreCase("update")){
			processUpdate(req,resp);
		}
		else if (req.getParameter("action").equalsIgnoreCase("summary")){
			processSummary(req,resp);
		}
		else if (req.getParameter("action").equalsIgnoreCase("delete")){
			processDelete(req,resp);
		}
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		if (req.getParameter("action").equalsIgnoreCase("getsummary")){
			processSummaryView(req,resp);
		}else if (req.getParameter("action").equalsIgnoreCase("getproduct")){
			processSelect(req,resp);
		}
		
	}
	
	protected void processDelete (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		int id = Integer.parseInt(req.getParameter("id"));
		Key productInBusketKey = KeyFactory.createKey("ProductInBusket", id);
		EntityManager em = EntityManagerFactory.get().createEntityManager();
		try {
			ProductInBusket pb = em.find(ProductInBusket.class, productInBusketKey);
			if (pb != null){
				em.getTransaction().begin();
				int num = pb.getNumInStock();
				em.remove(pb);
				em.getTransaction().commit();
				em.getTransaction().begin();
				Key productKey = KeyFactory.createKey("Product", pb.getProductId());
				Product p = em.find(Product.class, productKey);
				int numstock = p.getNumInStock();
				p.setNumInStock(numstock + num);
				em.getTransaction().commit();
				out.print("Deleted");
			}			    
		}catch (Exception ex) {
			out.println(ex);
			em.getTransaction().rollback();
        }
        finally {
            em.close();
            out.close();
        }	
	}

	protected void processInsert (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		Product product = new Product(
				req.getParameter("name"), 
				Double.parseDouble(req.getParameter("price")), 
				req.getParameter("imagePath"), 
				Integer.parseInt(req.getParameter("numInStock"))
		);
		EntityManager em = EntityManagerFactory.get().createEntityManager();
		try {
            em.persist(product);
            out.print("Insert successful!!");
		}catch (Exception ex) {
			out.println(ex);
        }
        finally {
            em.close();
            out.close();
        }	
	}
	
	protected void processUpdate (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		int id = Integer.parseInt(req.getParameter("id"));
		String owner = req.getParameter("owner");
		String strQuery = "SELECT o FROM ProductInBusket AS o WHERE productId = "+id+" and owner = '"+owner+"'";
		EntityManager em = EntityManagerFactory.get().createEntityManager();
		Gson gson = new Gson();
		try {
			Query queryProductInBusket = em.createQuery(strQuery);
			Key key = KeyFactory.createKey("Product", id);
			Product p = em.find(Product.class, key);
			int stock = p.getNumInStock();
			if (stock != 0){
				em.getTransaction().begin();
				p.setNumInStock(stock-1);
				ProductInBusket pb;
				em.getTransaction().commit();
				if (queryProductInBusket.getResultList().size() > 0){
					em.getTransaction().begin();
					pb = (ProductInBusket) queryProductInBusket.getResultList().get(0);
					int pbStock = pb.getNumInStock();
					pb.setNumInStock(pbStock+1);
					pb.setPrice(pb.getNumInStock()*p.getPrice());
					em.getTransaction().commit();
				}else{
					em.getTransaction().begin();
					pb = new ProductInBusket(owner, p.getName(), p.getPrice(), p.getImagePath(), 1, id);
					em.persist(pb);
					em.getTransaction().commit();
				}	
				out.println(gson.toJson(pb));
			}else{
				out.print("Out of stock!!");
			}
		}catch (Exception ex) {
			out.println(ex);
			em.getTransaction().rollback();
        }
        finally {
            em.close();
            out.close();
        }	
	}
	
	protected void processSummaryView (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		response.setContentType("application/json; charset=utf-8");
		PrintWriter out = response.getWriter();			
		EntityManager em = EntityManagerFactory.get().createEntityManager();
		Gson gson = new Gson();
		try{
			String mailTo = request.getParameter("tbEmail");
			String strquery = "SELECT o FROM ProductInBusket AS o WHERE owner = '"+mailTo+"'";
			Query query = em.createQuery(strquery);
			@SuppressWarnings("unchecked")
			List<ProductInBusket> results = (List<ProductInBusket>) query.getResultList();
			out.println(gson.toJson(results));
		} catch(Exception ex) {
            out.println(ex);
        } finally {
            em.close();
            out.close();
        }
	}
	
	protected void processSummary (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("<title>Summary Order</title>");
		out.println("</head>");
		out.println("<body>");
			
			String mailTo = request.getParameter("tbEmail");
			String mailSubject = "Online Stationery Store::Purchasing Confirmation";
			String strQuery2 = "SELECT o FROM ProductInBusket AS o WHERE owner = '"+mailTo+"'";
			String strQuery = "SELECT o FROM Customer AS o where email= '"+mailTo+"'";
			EntityManager em = EntityManagerFactory.get().createEntityManager();
			Query queryProductInBusket = em.createQuery(strQuery2);
			Query queryUser = em.createQuery(strQuery);
			@SuppressWarnings("unchecked")
			List<ProductInBusket> pb = (List<ProductInBusket>) queryProductInBusket.getResultList();
			Customer cus = (Customer) queryUser.getResultList().get(0);
			StringBuilder mailBody = new StringBuilder();
			mailBody.append("Hi, "+cus.getFirstName()+ " "+cus.getLastName()+"\n\n");
			mailBody.append("Thank you for your shopping on Online Stationery Store. \n");
			mailBody.append("Your order are :\n\n");
			float grandTotal=0.0f;
			for(int i=0;i<pb.size();i++){
				int j = i + 1; 
				mailBody.append(j+". "+pb.get(i).getName()+" Price: "+(pb.get(i).getPrice()/pb.get(i).getNumInStock())+"  Baht  Amount: "+pb.get(i).getNumInStock()+"  Total:"+ pb.get(i).getPrice()+"  Baht\n");
				grandTotal+=pb.get(i).getPrice();
				
				em.getTransaction().begin();
				em.remove(pb.get(i));
				em.getTransaction().commit();
			}
			
			mailBody.append("\nGrand Total :"+grandTotal+" Baht\n");
			mailBody.append("\nWe will send all items to following address:\n");
			mailBody.append("Address: "+cus.getAddress()+"\n");
			mailBody.append("City: "+cus.getCity()+"\n");
			mailBody.append("Country: "+cus.getCountry()+"\n");
			mailBody.append("Zipcode: "+cus.getZipCode()+"\n");
			mailBody.append("\nCheers,\n");
			mailBody.append("Online Stationery Store Team");
			
			Properties props = new Properties();
			Session session = Session.getDefaultInstance(props, null);
			
				try {
					Message msg = new MimeMessage(session);
					msg.setFrom(new InternetAddress("thanyaammyy@gmail.com","<No-Reply>Online-Shopping Team"));
//					msg.addRecipient(Message.RecipientType.BCC,
//							new InternetAddress("tamujinz@gmail.com"));
//					msg.addRecipient(Message.RecipientType.BCC,
//							new InternetAddress("doctor.aong@gmail.com"));
					msg.addRecipient(Message.RecipientType.TO,
					new InternetAddress(mailTo));
					msg.setSubject(mailSubject);
					msg.setText(mailBody.toString());
					Transport.send(msg);
					
					out.println("Please see your purchasing detail in your e-mail.<br />");
					out.println("<input type=\"button\" onclick=\"window.location = 'Index.html'\" value=\"Back to shopping\"/>");
				} catch (AddressException ex) {
					out.println("Invalid email address!!");
					out.println(ex);
					ex.printStackTrace();
				} catch (MessagingException ex) {
					out.println("Error while sending Email message");
					out.println(ex);
					ex.printStackTrace();
				} catch (Exception ex){
					em.getTransaction().rollback();
				}
		
	        finally {
	            
	            out.close();
	        }

			
		out.println("</body>");
		out.println("</html>");
		out.close();
	}
	
	protected void processSelect (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
		resp.setContentType("application/json; charset=utf-8");
		PrintWriter out = resp.getWriter();
		EntityManager em = EntityManagerFactory.get().createEntityManager();
		Gson gson = new Gson();
		try{
			Query query = em.createQuery("SELECT o FROM Product AS o");
			@SuppressWarnings("unchecked")
			List<Product> results = (List<Product>) query.getResultList();
			out.println(gson.toJson(results));
		} catch(Exception ex) {
            out.println(ex);
        } finally {
            em.close();
            out.close();
        }
	}
}
